package com.xusheng.cli.controller.open;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.xusheng.cli.common.base.Result;
import com.xusheng.cli.common.tools.UnitConvertUtils;
import com.xusheng.cli.entity.advertModule.Advert;
import com.xusheng.cli.entity.dictionaryModule.Category;
import com.xusheng.cli.entity.downloadStatisticsModule.DownloadStatistics;
import com.xusheng.cli.entity.favoritesModule.Favorites;
import com.xusheng.cli.entity.frontUserModule.FrontUser;
import com.xusheng.cli.entity.likesModule.Likes;
import com.xusheng.cli.entity.messageModule.Message;
import com.xusheng.cli.entity.proxyHostModule.ProxyHost;
import com.xusheng.cli.service.*;
import com.xusheng.cli.tools.IpUtil;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * 通用接口
 *
 * @author lyh
 * @since 2023-04-27 09:51
 */
@Slf4j
@RestController
@RequestMapping("/open/v1/common")
public class CommonController {

    @Resource
    private CategoryService categoryService;
    @Resource
    private AdvertService adService;

    @Resource
    private FavoritesService favoritesService;

    @Resource
    private LikesService likesService;
    @Resource
    private FrontUserService frontUserService;

    @Resource
    private MessageService messageService;

    @Value("${upload.path}")
    private String downloadPath;

    @Resource
    private ProxyHostThreeService proxyHostThreeService;
    @Resource
    private ProxyHostTwoService proxyHostTwoService;
    @Resource
    private ProxyHostService proxyHostService;

    @Resource
    private DownloadStatisticsService downloadStatisticsService;

    /**
     * 获取所有分类
     *
     * @return 返回结果
     */
    @GetMapping("/category")
    public Result<List<Category>> allCategory() {
        List<Category> list = categoryService.lambdaQuery()
                .orderByDesc(Category::getLevel)
                .orderByDesc(Category::getCreateTime)
                .list();
        return Result.success(list);
    }

    /**
     * 通过广告位置获取广告列表
     *
     * @param positionId 位置编号
     * @return 返回结果
     */
    @GetMapping("/ad/{positionId}")
    public Result<List<Advert>> getAd(@PathVariable long positionId) {
        List<Advert> list = adService.lambdaQuery()
                .eq(Advert::getPositionId, positionId)
                .orderByDesc(Advert::getCreateId)
                .list();
        Collections.reverse(list);
        return Result.success(list);
    }

    /**
     * 随机底部广告接口
     *
     * @param positionId
     * @return
     */
    @GetMapping("/ad/random/{positionId}")
    public Result<List<Advert>> getRandomAd(@PathVariable long positionId) {
        List<Advert> list = adService.lambdaQuery()
                .eq(Advert::getPositionId, positionId)
                .orderByDesc(Advert::getCreateId)
                .list();
        // 随机获取一条
        Random rand = new Random();
        Advert advert = list.get(rand.nextInt(list.size()));
        List<Advert> randomList = new ArrayList<>();
        randomList.add(advert);
        return Result.success(randomList);
    }

    /**
     * 获取当前视频的点赞和关注数量
     */
    @GetMapping("/getCountByLikeFollow/{videoId}")
    public Result<Object> getCountByLikeFollow(@PathVariable long videoId) {
        // 获取收藏数量
        Favorites favorites = new Favorites();
        favorites.setVideoId(videoId);
        long favoritesCount = favoritesService.count(new QueryWrapper<>(favorites));
        // 获取点赞数量
        Likes likes = new Likes();
        likes.setVideoId(videoId);
        long likesCount = likesService.count(new QueryWrapper<>(likes));
        JSONObject object = new JSONObject();
        object.put("favorites", favoritesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(favoritesCount) : favoritesCount);
        object.put("likes", likesCount > 10000 ? UnitConvertUtils.toTenThousandUnit(likesCount) : likesCount);
        return Result.success(object);
    }

    /**
     * 点击广告
     *
     * @param userId
     * @return
     */
    @GetMapping("clickAd")
    public Result<Object> clickAd(Long userId) {
        if (userId != null) {
            FrontUser user = frontUserService.getById(userId);
            user.setClickAd(true);
            return Result.isSuccess(frontUserService.updateById(user));
        } else {
            return Result.success();
        }
    }

    /**
     * 获取首页展示公告信息
     *
     * @return
     */
    @GetMapping("homeShow")
    public Result<Message> getHomeShow() {
        return Result.success(messageService.getOne(new LambdaQueryWrapper<>(new Message()).eq(Message::getHomeShow, true)));
    }

    /**
     * 生成二维码
     *
     * @param request
     * @return
     */
    @GetMapping("qrCode")
    public void qrCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String host = request.getScheme() + "://" + request.getRemoteHost();
        String serverName = request.getScheme() + "://" + request.getServerName();
        log.info("serverName:{},host:{}", serverName, host);
        // 设置二维码的内容
        String content = serverName + "/video-platform/open/v1/common/downloadApp";
        // 设置二维码的配置
        QrConfig config = new QrConfig(300, 300);
        config.setErrorCorrection(ErrorCorrectionLevel.valueOf("M")); // 设置纠错级别
        // 生成二维码并保存到文件
//        QrCodeUtil.generate(content, config, FileUtil.file("qrcode.png"));

        // 或者直接输出到流
        QrCodeUtil.generate(content, config, ImgUtil.IMAGE_TYPE_JPEG, response.getOutputStream());
    }

    /**
     * APP生成二维码
     *
     * @param request
     * @return
     */
    @GetMapping("appQrCode")
    public void appQrCode(String proxyId, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String host = request.getScheme() + "://" + request.getRemoteHost();
        String serverName = request.getScheme() + "://" + request.getServerName();
        log.info("serverName:{},host:{}", serverName, host);
        // 设置二维码的内容
        String content = serverName + "/video-platform/open/v1/common/downloadApp?proxyId=" + proxyId;
        // 设置二维码的配置
        QrConfig config = new QrConfig(300, 300);
        config.setErrorCorrection(ErrorCorrectionLevel.valueOf("M")); // 设置纠错级别
        // 生成二维码并保存到文件
//        QrCodeUtil.generate(content, config, FileUtil.file("qrcode.png"));

        // 或者直接输出到流
        QrCodeUtil.generate(content, config, ImgUtil.IMAGE_TYPE_JPEG, response.getOutputStream());
    }

    /**
     * 扫码下载app
     *
     * @param request
     * @return
     */
    @GetMapping("downloadApp")
    public void downloadApp(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String host = request.getScheme() + "://" + request.getRemoteHost();
        String serverName = request.getServerName();
        String apkPath;
        // 创建代理文件夹
        String directoryPath = downloadPath + "app/" + serverName;
        File directory = new File(directoryPath);
        if (!directory.exists()) {
            directory.mkdir();
        }
        File file = new File(directoryPath + "/video_app.apk");
        if (!file.exists()) {
            String command = "python3 " + downloadPath + "app/script.py " + serverName + " " + directoryPath + "/video_app.apk";
            log.info("脚本命令为{}", command);
            String s = RuntimeUtil.execForStr(command);
            log.info("脚本命令回调{}", s);
        }
        apkPath = directoryPath + "/video_app.apk";
        //            return FileUtils.downloadFileByFullName(directoryPath + "/video_app.apk", "video_app.apk");
        // 读到流中
        InputStream inputStream = new FileInputStream(apkPath);// 文件的存放路径
        response.reset();
        response.setContentType("application/octet-stream");
        String filename = new File(apkPath).getName();
        response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"));
        ServletOutputStream outputStream = response.getOutputStream();
        byte[] b = new byte[1024];
        int len;
        //从输入流中读取一定数量的字节，并将其存储在缓冲区字节数组中，读到末尾返回-1
        while ((len = inputStream.read(b)) > 0) {
            outputStream.write(b, 0, len);
        }
        inputStream.close();
        //生成统计
        downloadStatistics(IpUtil.getClientIp());
    }

    public void downloadAppOld(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String host = request.getScheme() + "://" + request.getRemoteHost();
        String serverName = request.getServerName();
        Long proxyId = null;
        if (StrUtil.isNotBlank(serverName)) {
            Long proxyThree = proxyHostThreeService.selectProxyByThree(serverName);
            if (proxyThree == null) {
                Long proxyTwo = proxyHostTwoService.selectProxyByTwo(serverName);
                if (proxyTwo == null) {
                    ProxyHost proxyHost = proxyHostService.lambdaQuery().eq(ProxyHost::getHost, serverName).one();
                    if (proxyHost != null) {
                        proxyId = proxyHost.getProxyId();
                    }
                } else {
                    proxyId = proxyTwo;
                }
            } else {
                proxyId = proxyThree;
            }
        }
        String apkPath;
        if (proxyId != null) {
            // 创建代理文件夹
            String directoryPath = downloadPath + "app/" + proxyId;
            File directory = new File(directoryPath);
            if (!directory.exists()) {
                directory.mkdir();
            }
            File file = new File(directoryPath + "/video_app.apk");
            if (!file.exists()) {
                String command = "python3 " + downloadPath + "app/script.py " + proxyId + " " + directoryPath + "/video_app.apk";
                log.info("脚本命令为{}", command);
                String s = RuntimeUtil.execForStr(command);
                log.info("脚本命令回调{}", s);
            }
            apkPath = directoryPath + "/video_app.apk";
            //            return FileUtils.downloadFileByFullName(directoryPath + "/video_app.apk", "video_app.apk");
        } else {
            apkPath = downloadPath + "app/video_app.apk";
            //            return FileUtils.downloadFileByFullName(downloadPath + "app/video_app.apk", "video_app.apk");
        }
        // 读到流中
        InputStream inputStream = new FileInputStream(apkPath);// 文件的存放路径
        response.reset();
        response.setContentType("application/octet-stream");
        String filename = new File(apkPath).getName();
        response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"));
        ServletOutputStream outputStream = response.getOutputStream();
        byte[] b = new byte[1024];
        int len;
        //从输入流中读取一定数量的字节，并将其存储在缓冲区字节数组中，读到末尾返回-1
        while ((len = inputStream.read(b)) > 0) {
            outputStream.write(b, 0, len);
        }
        inputStream.close();
    }

    /**
     * app扫码下载app
     *
     * @param request
     * @return
     */
    @GetMapping("appDownloadApp")
    public void appDownloadApp(String proxyId, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String apkPath;
        if (StrUtil.isNotBlank(proxyId)) {
            // 创建代理文件夹
            String directoryPath = downloadPath + "app/" + proxyId;
            File directory = new File(directoryPath);
            if (!directory.exists()) {
                directory.mkdir();
            }
            File file = new File(directoryPath + "/video_app.apk");
            if (!file.exists()) {
                String command = "python3 " + downloadPath + "app/script.py " + proxyId + " " + directoryPath + "/video_app.apk";
                log.info("脚本命令为{}", command);
                String s = RuntimeUtil.execForStr(command);
                log.info("脚本命令回调{}", s);
            }
            apkPath = directoryPath + "/video_app.apk";
        } else {
            apkPath = downloadPath + "app/video_app.apk";
        }
        // 读到流中
        InputStream inputStream = new FileInputStream(apkPath);// 文件的存放路径
        response.reset();
        response.setContentType("application/octet-stream");
        String filename = new File(apkPath).getName();
        response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"));
        ServletOutputStream outputStream = response.getOutputStream();
        byte[] b = new byte[1024];
        int len;
        //从输入流中读取一定数量的字节，并将其存储在缓冲区字节数组中，读到末尾返回-1
        while ((len = inputStream.read(b)) > 0) {
            outputStream.write(b, 0, len);
        }
        inputStream.close();
        //生成统计
        downloadStatistics(IpUtil.getClientIp());
    }

    /**
     * 生成下载统计
     *
     * @param ip
     */
    public void downloadStatistics(String ip) {
        log.info("当前用户IP为{}", ip);
        DownloadStatistics data = new DownloadStatistics();
        data.setIp(ip);
        data.setType(0);
        data.setAddr(IpUtil.getAddress(ip));
        log.info("正在生成下载记录");
        downloadStatisticsService.save(data);
    }

    @GetMapping("test")
    public void test(String ip) {
        log.info("当前用户IP为{}", ip);
        DownloadStatistics data = new DownloadStatistics();
        data.setIp(ip);
        data.setType(0);
        data.setAddr(IpUtil.getAddress(ip));
        log.info("正在生成下载记录");
        downloadStatisticsService.save(data);
    }

    @GetMapping("hostShow")
    public Result hostShow(HttpServletRequest request) {
        // 校验域名是否匹配
        List<ProxyHost> list = proxyHostService.lambdaQuery().eq(ProxyHost::getHost, request.getServerName()).list();
        if (list.size() > 0) {
            DownloadStatistics downloadStatistics = new DownloadStatistics();
            downloadStatistics.setIp(IpUtil.getClientIp());
            downloadStatistics.setType(2);
            downloadStatistics.setAddr(IpUtil.getAddress(IpUtil.getClientIp()));
            downloadStatistics.setHost(request.getServerName());
            log.info("正在生成展示记录");
            return Result.isSuccess(downloadStatisticsService.save(downloadStatistics));
        } else {
            return Result.error();
        }
    }
}
